home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Online / Qpopper / popauth.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-30  |  11.3 KB  |  546 lines

  1. /*  */
  2. /* popauth.c - manipulate POP authorization DB */
  3. #ifndef    lint
  4. static char ident[] = "@(#)$Id: popauth.c,v 1.9 1996/05/30 00:37:41 mark Exp mark $";
  5. #endif    /* lint */
  6.  
  7. #undef    DBM        /* used by mts.c and ndbm.h */
  8. #include <ndbm.h>
  9. #include <pwd.h>
  10. #include <stdio.h>
  11. #ifdef __STDC__
  12. #include <stdlib.h>
  13. #include <stdarg.h>
  14. #else
  15. #include <varargs.h>
  16. #endif
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. #include <fcntl.h>
  20. #include <errno.h>
  21.  
  22. #if defined(SOLARIS2) || defined(SYSV) || defined(AIX)
  23. #include    <string.h>
  24. #define bcopy(src,dest,len)    (void) (memcpy(dest,src,len))
  25. #define bzero(dest,len)      (void) (memset(dest, (char)NULL, len))
  26. #define bcmp(b1,b2,n)        memcmp(b1,b2,n)
  27. #ifndef index
  28. # define index(s,c)        strchr(s,c)
  29. #endif
  30. #ifndef rindex
  31. # define rindex(s,c)        strrchr(s,c)
  32. #endif
  33. #include "flock.h"
  34. #else
  35. #include <strings.h>
  36. #include <sys/file.h>
  37. #endif
  38.  
  39. #ifdef BSDI
  40. #define BSD44_DBM
  41. #endif
  42.  
  43. #ifdef NEED_STRERROR
  44. char *strerror();
  45. #endif
  46.  
  47. #define    UID_T    uid_t
  48.  
  49. static struct swit {
  50.     char *name;
  51. } switches[] = {
  52. #define    INITSW    0
  53.     "init", 
  54. #define    LISTSW    1
  55.     "list", 
  56. #define    USERSW    2
  57.     "user", 
  58. #define    DELESW    3
  59.     "delete", 
  60.  
  61.     NULL,
  62. };
  63.  
  64. static char   *program;
  65.  
  66. #ifdef __STDC__
  67. static void
  68. adios(const char *fmt, ...)
  69. #else
  70. static void
  71. adios(va_alist)
  72. va_dcl
  73. #endif
  74. {
  75.     va_list ap;
  76. #ifndef __STDC__
  77.     char *fmt;
  78. #endif
  79.  
  80.     (void) fprintf(stderr, "%s: ", program);
  81. #ifdef __STDC__
  82.     va_start(ap, fmt);
  83. #else
  84.     va_start(ap);
  85.     fmt = va_arg(ap, char *);
  86. #endif
  87.     (void) vfprintf(stderr, fmt, ap);
  88.     (void) fprintf(stderr, "\n");
  89.     va_end(fmt);
  90.     exit(1);
  91.     /*NOTREACHED*/
  92. }
  93.  
  94. #ifdef STRDUP
  95. #include <stddef.h>
  96.  
  97. char *
  98. strdup(str)
  99.         char *str;
  100. {
  101.     int len;
  102.     char *copy;
  103.  
  104.     len = strlen(str) + 1;
  105.     if (!(copy = malloc((u_int)len)))
  106.     return((char *)NULL);
  107.     bcopy(str, copy, len);
  108.     return(copy);
  109. }
  110. #endif
  111.  
  112. /*
  113.  * Obscure password so a cleartext search doesn't come up with
  114.  * something interesting.
  115.  *
  116.  */
  117.  
  118. char *
  119. obscure(string)
  120. char *string;
  121. {
  122.     unsigned char *cp, *newstr;
  123.  
  124.     cp = newstr = (unsigned char *)strdup(string);
  125.  
  126.     while (*cp) {
  127.         *cp++ ^= 0xff;
  128.     }
  129.  
  130.     return((char *)newstr);
  131. }
  132.  
  133. /* Use GNU_PASS for longer passwords on systems that support termios */
  134.  
  135. #ifndef GNU_PASS
  136. char *getpass();
  137. #else
  138.  
  139. /* Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
  140. This file is part of the GNU C Library.
  141.  
  142. The GNU C Library is free software; you can redistribute it and/or
  143. modify it under the terms of the GNU Library General Public License as
  144. published by the Free Software Foundation; either version 2 of the
  145. License, or (at your option) any later version.
  146.  
  147. The GNU C Library is distributed in the hope that it will be useful,
  148. but WITHOUT ANY WARRANTY; without even the implied warranty of
  149. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  150. Library General Public License for more details.
  151.  
  152. You should have received a copy of the GNU Library General Public
  153. License along with the GNU C Library; see the file COPYING.LIB.  If
  154. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  155. Cambridge, MA 02139, USA.  */
  156.  
  157. /* It is desireable to use this bit on systems that have it.
  158.    The only bit of terminal state we want to twiddle is echoing, which is
  159.    done in software; there is no need to change the state of the terminal
  160.    hardware.  */
  161.  
  162. #include <stdio.h>
  163. #include <termios.h>
  164. #include <unistd.h>
  165.  
  166. #ifndef TCSASOFT
  167. #define TCSASOFT 0
  168. #endif
  169.  
  170. #ifdef SSIZET
  171. typedef SSIZET ssize_t;
  172. #endif
  173.  
  174. char *
  175. getpass (prompt)
  176. #if defined(HPUX)
  177. char *prompt;
  178. #else
  179. const char *prompt;
  180. #endif
  181. {
  182.   FILE *in, *out;
  183.   struct termios t;
  184.   int echo_off;
  185.   static char *buf = NULL;
  186.   static size_t bufsize = 0;
  187.   ssize_t nread;
  188.  
  189.   /* Try to write to and read from the terminal if we can.
  190.      If we can't open the terminal, use stderr and stdin.  */
  191.  
  192.   in = fopen ("/dev/tty", "w+");
  193.   if (in == NULL)
  194.     {
  195.       in = stdin;
  196.       out = stderr;
  197.     }
  198.   else
  199.     out = in;
  200.  
  201.   /* Turn echoing off if it is on now.  */
  202.  
  203.   if (tcgetattr (fileno (in), &t) == 0)
  204.     {
  205.       if (t.c_lflag & ECHO)
  206.     {
  207.       t.c_lflag &= ~ECHO;
  208.       echo_off = tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0;
  209.       t.c_lflag |= ECHO;
  210.     }
  211.       else
  212.     echo_off = 0;
  213.     }
  214.   else
  215.     echo_off = 0;
  216.  
  217.   /* Write the prompt.  */
  218.   fputs (prompt, out);
  219.   fflush (out);
  220.  
  221.   /* Read the password.  */
  222. #ifdef NO_GETLINE
  223.   bufsize = 256;
  224.   buf = (char *)malloc(256);
  225.   nread = (fgets(buf, (size_t)bufsize, in) == NULL) ? 1 : strlen(buf);
  226.   rewind(in);
  227.   fputc('\n', out);
  228. #else
  229.   nread = __getline (&buf, &bufsize, in);
  230. #endif
  231.   if (nread < 0 && buf != NULL)
  232.     buf[0] = '\0';
  233.   else if (buf[nread - 1] == '\n')
  234.     /* Remove the newline.  */
  235.     buf[nread - 1] = '\0';
  236.  
  237.   /* Restore echoing.  */
  238.   if (echo_off)
  239.     (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t);
  240.  
  241.   if (in != stdin)
  242.     /* We opened the terminal; now close it.  */
  243.     fclose (in);
  244.  
  245.   return buf;
  246. }
  247. #endif
  248.  
  249. /* ARGSUSED */
  250.  
  251. main (argc, argv)
  252. int    argc;
  253. char   *argv[];
  254. {
  255.     UID_T   myuid;
  256.     int        flags,
  257.         i,
  258.         delesw = 0,
  259.         initsw = 0,
  260.         insist,
  261.         listsw = 0,
  262.         popuser = 0;
  263.     long    clock;
  264.     char   *bp,
  265.        *cp,
  266.        *usersw = NULL,
  267.         buf[100],
  268.         obuf[100];
  269.     struct  passwd *pw;
  270.     datum   key,
  271.         value;
  272.     DBM    *db;
  273.     char    apop_dir[BUFSIZ];
  274. #ifndef BSD44_DBM
  275.     char    apop_pag[BUFSIZ];
  276. #endif
  277.     int     f;
  278.  
  279.     program = argv[0];
  280.     argv++;
  281.     argc--;
  282.  
  283.     while (argc > 0) {
  284.     cp = argv[0];
  285.     if (*cp == '-') {
  286.         int i, v;
  287.  
  288.         i = 0;
  289.         v = -1;
  290.         for(i = 0; switches[i].name; i++) {
  291.         if(strcmp(&cp[1], switches[i].name) == 0) {
  292.             v = i;
  293.             break;
  294.         }
  295.         }
  296.         cp++;
  297.         switch (v) {
  298.         default:
  299.             adios ("-%s unknown option", cp);
  300.         case INITSW:
  301.             initsw = 1, listsw = 0; delesw = 0;
  302.             break;
  303.         case LISTSW:
  304.             listsw = 1, initsw = 0; delesw = 0;
  305.             break;
  306.         case DELESW:
  307.             delesw = 1, initsw = 0; listsw = 0;
  308.             if (argc < 2 || argv[1][0] == '-')
  309.             adios ("missing argument to %s", argv[0]);
  310.             usersw = argv[1];
  311.             argc--;
  312.             argv++;
  313.             break;
  314.         case USERSW:
  315.             if (argc < 2 || argv[1][0] == '-')
  316.             adios ("missing argument to %s", argv[0]);
  317.             usersw = argv[1];
  318.             argc--;
  319.             argv++;
  320.             if (delesw)
  321.             fprintf(stderr, "Warning: user '%s' will now be deleted\n", usersw);
  322.             break;
  323.         }
  324.     }
  325.     else
  326.         adios ("usage: %s [[-init]|[-list]|[-user name]|[-delete name]]", program);
  327.     argc--;
  328.     argv++;
  329.     }
  330.  
  331.  
  332. #ifndef    APOP
  333.     adios ("not compiled with APOP option");
  334. #else
  335.  
  336.     myuid = getuid();
  337.  
  338.     if ((pw = getpwnam (POPUID)) == NULL)
  339.     adios ("\"%s\": user-id unknown", POPUID);
  340.  
  341.     if (pw->pw_uid == myuid)
  342.     popuser = 1;
  343.  
  344.     if (myuid && !popuser && (delesw || initsw || listsw || (usersw != NULL)))
  345.     adios("Only superuser or user '%s' can perform the requested function",
  346.         POPUID);
  347.  
  348.     if (myuid && initsw)
  349.     adios("Only superuser can init the database");
  350.  
  351.     (void) strncpy(apop_dir, APOP, sizeof(apop_dir) - 5);
  352. #ifdef BSD44_DBM
  353.     (void) strcat(apop_dir, ".db");
  354. #else
  355.     (void) strncpy(apop_pag, APOP, sizeof(apop_pag) - 5);
  356.     (void) strcat(apop_pag, ".pag");
  357.     (void) strcat(apop_dir, ".dir");
  358. #endif
  359.  
  360.     if (delesw) {
  361.     if (myuid && !popuser)
  362.         adios ("Only root or %s may delete entries", POPUID);
  363.  
  364.     if ((db = dbm_open (APOP, O_RDWR, 0)) == NULL)
  365.         adios ("%s: unable to open POP authorization DB", APOP);
  366.     
  367.     key.dsize = strlen (key.dptr = usersw) + 1;
  368.  
  369.     value = dbm_fetch(db, key);
  370.     if (value.dptr == NULL)
  371.         adios("User '%s' not found in apop database", usersw);
  372.  
  373.     if (dbm_delete(db, key) < 0)
  374.         adios("Unable to delete user '%s' from apop database", usersw);
  375.  
  376.     dbm_close (db);
  377.  
  378.     exit (0);
  379.     }
  380.  
  381.     if (initsw) {
  382.     struct stat st;
  383.  
  384.     setuid(myuid);
  385.  
  386.     if (stat (apop_dir, &st) != -1) {
  387.         char ibuf[30];
  388.         
  389.         printf("Really initialize POP authorization DB? ");
  390.         if(fgets(ibuf, sizeof(ibuf), stdin) == NULL || ibuf[0] != 'y')
  391.         exit (1);
  392.         (void) unlink (apop_dir);
  393. #ifndef BSD44_DBM
  394.         (void) unlink (apop_pag);
  395. #endif
  396.     }
  397.     if ((db = dbm_open (APOP, O_RDWR | O_CREAT, 0600)) == NULL)
  398.         adios ("unable to create POP authorization DB: %s", 
  399.             strerror(errno));
  400.     dbm_close (db);
  401.     if (chown (apop_dir, pw->pw_uid, pw->pw_gid) == -1 
  402. #ifndef BSD44_DBM
  403.      || chown (apop_pag, pw->pw_uid, pw->pw_gid) == -1
  404. #endif
  405.         )
  406.         adios ("error setting ownership of POP authorization DB: %s", 
  407.         strerror(errno));
  408.  
  409.     exit (0);
  410.     }
  411.  
  412.     if ((db = dbm_open (APOP, O_RDONLY, 0)) == NULL)
  413.     adios ("unable to open POP authorization DB: %s", strerror(errno));
  414.  
  415.     f = open (apop_dir, listsw ? O_RDONLY : O_RDWR);
  416.     if(f == -1)
  417.     adios ("%s: unable to open POP authorization DB", apop_dir);
  418.  
  419.     if (flock (f, LOCK_SH) == -1)
  420.     adios ("%s: unable to lock POP authorization DB", apop_dir);
  421.  
  422.     if (listsw) {
  423.     if (usersw) {
  424.         key.dsize = strlen (key.dptr = usersw) + 1;
  425.         value = dbm_fetch (db, key);
  426.         if (value.dptr == NULL)
  427.         adios ("no such entry in POP authorization DB");
  428.         printf ("%s\n", key.dptr);
  429.     }
  430.     else
  431.         for (key = dbm_firstkey (db); key.dptr; key = dbm_nextkey (db)) {
  432.         printf ("%s", key.dptr);
  433.         value = dbm_fetch (db, key);
  434.         if (value.dptr == NULL)
  435.             printf (" - no information?!?\n");
  436.         else {
  437.             printf ("\n");
  438.         }
  439.         }
  440.  
  441.     dbm_close (db);
  442.  
  443.     exit (0);
  444.     }
  445.  
  446.     if (usersw == NULL) {
  447.     if ((pw = getpwuid(myuid)) == NULL)
  448.         adios("Sorry, don't know who uid %d is.", myuid);
  449.     usersw = pw->pw_name;
  450.     } else {
  451.     if ((pw = getpwnam(usersw)) == NULL)
  452.         adios("Sorry, don't know who uid %s is.", usersw);
  453.     usersw = pw->pw_name;
  454.     }
  455.  
  456.     fprintf (stderr, "Changing POP password for %s.\n", usersw);
  457.  
  458.     key.dsize = strlen (key.dptr = usersw) + 1;
  459.     value = dbm_fetch (db, key);
  460.     if (myuid && !popuser && value.dptr != NULL) {
  461.     if (((i = strlen(strncpy(obuf, getpass("Old password:"), sizeof(obuf)))) == 0) ||
  462.         ((value.dsize - 1) != i) ||
  463.         (strncmp(obuf, value.dptr, i) &&
  464.              strncmp(obuf, obscure(value.dptr), i))) {
  465.         adios("Sorry, password entered incorrectly\n");
  466.     }
  467.     }
  468.     dbm_close (db);
  469.  
  470. #ifdef    lint
  471.     flags = 0;
  472. #endif    /* lint */
  473.     for (insist = 0; insist < 2; insist++) {
  474.     int    i;
  475.     char    c;
  476.  
  477.     if (insist)
  478.         printf ("Please use %s.\n",
  479.             flags == 1 ? "at least one non-numeric character"
  480.             : "a longer password");
  481.  
  482.     if (((i = strlen(strncpy(buf, getpass("New password:"), sizeof(buf)))) == 0) ||
  483.           !strncmp(buf, obuf, i)) {
  484.         fprintf (stderr, "Password unchanged.\n");
  485.         exit (1);
  486.     }
  487.  
  488.     flags = 0;
  489.     for (cp = buf; c = *cp++;)
  490.         if (c >= 'a' && c <= 'z')
  491.         flags |= 2;
  492.         else
  493.         if (c >= 'A' && c <= 'Z')
  494.             flags |= 4;
  495.         else
  496.             if (c >= '0' && c <= '9')
  497.             flags |= 1;
  498.             else
  499.             flags |= 8;
  500.  
  501.     if ((flags >= 7 && i >= 4)
  502.         || ((flags == 2 || flags == 4) && i >= 6)
  503.         || ((flags == 3 || flags == 5 || flags == 6) && i >= 5))
  504.         break;
  505.     }
  506.  
  507.     if (strcmp(buf, getpass("Retype new password:"))) {
  508.     fprintf (stderr, "Mismatch - password unchanged.\n");
  509.     exit (1);
  510.     }
  511.  
  512.     if ((db = dbm_open(APOP, O_RDWR, 0)) == NULL)
  513.     adios("%s: unable to open POP authorization DB", APOP);
  514.  
  515.     if (flock(f, LOCK_EX) == -1)
  516.     adios("%s: unable to lock POP authorization DB", apop_dir);
  517.  
  518.     key.dsize = strlen (key.dptr = usersw) + 1;
  519.  
  520.     value.dptr = obscure(buf);
  521.     value.dsize = strlen(value.dptr) + 1;
  522.  
  523.     if (dbm_store (db, key, value, DBM_REPLACE))
  524.     adios ("POP authorization DB may be corrupt?!?");
  525.     dbm_close (db);
  526. #endif
  527.  
  528.     exit (0);
  529.     /* NOTREACHED */
  530. }
  531.  
  532. #ifdef NEED_STRERROR
  533. char *
  534. strerror(e)
  535.     int e;
  536. {
  537.     extern char *sys_errlist[];
  538.     extern int sys_nerr;
  539.  
  540.     if(e < sys_nerr)
  541.         return(sys_errlist[e]);
  542.     else
  543.         return("unknown error");
  544. }
  545. #endif
  546.